// File:       piscmd06.c++
// Version:    1.00
// Author:     (c) Miles Sabin, 1997
// Purpose:    string extraction command

// Change log:
//  27/03/97   v. 1.00

#include "piscmds.h"

#include <ctype.h>
#include "istream.h"
#include "streambuf.h"


// Implementation of ExtractStringCommand

ExtractStringCommand::ExtractStringCommand
  (basic_istream_char& is, char* s, streamsize n, int delim,
   bool extract_delim, bool ws_delim, bool noskipws)
  : s_(s),
    n_(n),
    delim_(delim),
    extract_delim_(extract_delim),
    ws_delim_(ws_delim),
    gcount_(0)
  { execute_template(is, noskipws); }

ExtractStringCommand::~ExtractStringCommand()
  {}

ios::iostate ExtractStringCommand::execute(basic_istream_char& is)
  {
    ios::iostate state = ios::goodbit;

    basic_streambuf_char* sb = is.rdbuf();

    int c = sb->sgetc();
    while(c != basic_istream_char::traits::eof() && (ws_delim_ ? !isspace(c) : c != delim_) && n_ > 0)
    {
      *s_++ = c;
      --n_;
      ++gcount_;

      c = sb->snextc();
    }

    *s_ = basic_istream_char::traits::eos();

    if(c == basic_istream_char::traits::eof())
      state |= ios::eofbit;
    else if(c == delim_ && extract_delim_)
    {
      sb->sbumpc();
      ++gcount_;
    }

    if(gcount_ == 0)
      state |= ios::failbit;

    return state;
  }


// Implementation of basic_istream_char

basic_istream_char& basic_istream_char::get(char* s, streamsize n, char delim)
  {
    gcount_ = 0;

    ExtractStringCommand cmd(*this, s, n-1, delim, false, false, true);
    gcount_ = cmd.gcount();

    return *this;
  }

basic_istream_char& basic_istream_char::getline(char* s, streamsize n, char delim)
  {
    gcount_ = 0;

    ExtractStringCommand cmd(*this, s, n-1, delim, true, false, true);
    gcount_ = cmd.gcount();

    return *this;
  }


// implementation of basic_istream_char free fns

basic_istream_char& operator>>(basic_istream_char& is, char* s)
{
  int n = is.width();
  if(n <= 0)
    n = 1<<24;

  ExtractStringCommand cmd(is, s, n-1, basic_istream_char::traits::eof(), false, true);
  is.width(0);
  return is;
}

